﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NetworkManagement;

namespace LorraineSec.MessageLib.Messages
{
    public sealed class DeviceCallbackMessage : EncryptedMessage
    {
        #region Format Constants
        /*
         * Format:
         *      1            8                 2                  2            x           y
         * | EventID | EventTimeStamp |  DeviceSerialLength | DataLength | DeviceSerial | Data |
         * 
         */

        private const int ENC_EVENTID_LENGTH = 1;
        private const int ENC_TIMESTAMP_LENGTH = 8;
        private const int ENC_SERIALLEN_LENGTH = 2;
        private const int ENC_DATALEN_LENGTH = 2;
        
        private const int ENC_EVENTID_OFFSET = 0;
        private const int ENC_TIMESTAMP_OFFSET = ENC_EVENTID_OFFSET + ENC_EVENTID_LENGTH;
        private const int ENC_SERIALLEN_OFFSET = ENC_TIMESTAMP_OFFSET + ENC_TIMESTAMP_LENGTH;
        private const int ENC_DATALEN_OFFSET = ENC_SERIALLEN_OFFSET + ENC_SERIALLEN_LENGTH;
        private const int ENC_SERIAL_OFFSET = ENC_DATALEN_OFFSET + ENC_DATALEN_LENGTH;

        private const int ENC_KNOWN_LENGTH = ENC_EVENTID_LENGTH + ENC_TIMESTAMP_LENGTH + ENC_SERIALLEN_LENGTH + ENC_DATALEN_LENGTH;
        #endregion

        public DeviceEvent EventType;
        public DateTime EventTimestamp;
        public string DeviceSerial;
        public byte[] DeviceData;

        public enum DeviceEvent
        {
            ATTACH,
            DETACH,
            VALUE_CHANGE,
        }

        public DeviceCallbackMessage()
        {
            init();
        }

        public DeviceCallbackMessage(byte[] bytes)
            : base(bytes)
        {
            init();
            decode();
        }

        private void init()
        {
            MessageID = (ushort)LorraineSecMessageFactory.MessageID.DEVICE_CALLBACK;
        }

        public override void decrypt(CryptoManager crypt)
        {
            base.decrypt(crypt);
            EventType = (DeviceEvent)Bytes.getByte(encData, ENC_EVENTID_OFFSET);
            EventTimestamp = new DateTime(Bytes.getInt64(encData, ENC_TIMESTAMP_OFFSET));
            ushort len = Bytes.getUInt16(encData, ENC_SERIALLEN_OFFSET);
            DeviceSerial = Bytes.getString(encData, ENC_SERIAL_OFFSET, len);
            len = Bytes.getUInt16(encData, ENC_DATALEN_OFFSET);
            DeviceData = Bytes.getByteArray(encData, ENC_SERIAL_OFFSET + DeviceSerial.Length, len);   
        }

        public override void encrypt(CryptoManager crypt)
        {
            encData = new byte[ENC_KNOWN_LENGTH + DeviceSerial.Length];
            Bytes.setValue(encData, ENC_EVENTID_OFFSET, (byte)EventType);
            Bytes.setValue(encData, ENC_TIMESTAMP_OFFSET, EventTimestamp.Ticks);
            Bytes.setValue(encData, ENC_SERIALLEN_OFFSET, (ushort)DeviceSerial.Length);
            Bytes.setValue(encData, ENC_DATALEN_OFFSET, (ushort)DeviceData.Length);
            Bytes.setValue(encData, ENC_SERIAL_OFFSET, DeviceSerial);
            Bytes.setValue(encData, ENC_SERIAL_OFFSET + DeviceSerial.Length, DeviceData);
            base.encrypt(crypt);
        }


    }
}
